import os
import re
import json
import urllib.parse
from flask import Flask, request, redirect, send_file, make_response, render_template
from werkzeug.utils import secure_filename
from minio import Minio
from minio.error import S3Error
from flask_cors import CORS

# 配置 Flask 应用
app = Flask(__name__)
CORS(app)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'md', 'png', 'jpg', 'jpeg', 'gif'}


# 检查文件是否是允许的类型
def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']


# 确保 uploads 目录存在
if not os.path.exists(app.config['UPLOAD_FOLDER']):
    os.makedirs(app.config['UPLOAD_FOLDER'])


# MinIO 客户端封装类
class MinIOClient:
    def __init__(self, endpoint, access_key, secret_key, secure=False):
        self.client = Minio(
            endpoint,
            access_key=access_key,
            secret_key=secret_key,
            secure=secure
        )
        self.endpoint = endpoint
        self.secure = secure

    def create_bucket(self, bucket_name):
        try:
            if not self.client.bucket_exists(bucket_name):
                self.client.make_bucket(bucket_name)
            print(f"Bucket '{bucket_name}' is ready.")
        except S3Error as e:
            print(f"Error checking/creating bucket: {e}")

    def set_bucket_policy(self, bucket_name):
        try:
            policy = {
                "Version": "2012-10-17",
                "Statement": [
                    {
                        "Effect": "Allow",
                        "Principal": {"AWS": ["*"]},
                        "Action": ["s3:GetObject"],
                        "Resource": [f"arn:aws:s3:::{bucket_name}/*"]
                    }
                ]
            }
            policy_json = json.dumps(policy)
            self.client.set_bucket_policy(bucket_name, policy_json)
            print(f"Bucket '{bucket_name}' is now publicly accessible.")
        except S3Error as e:
            print(f"Error setting bucket policy: {e}")

    def upload_file(self, bucket_name, file_path, object_name):
        try:
            self.client.fput_object(bucket_name, object_name, file_path)
            print(f"'{object_name}' is successfully uploaded.")
        except S3Error as e:
            print(f"Error uploading file: {e}")
            return None

        protocol = "http" if not self.secure else "https"
        object_url = f"{protocol}://{self.endpoint}/{bucket_name}/{object_name}"
        return object_url


# Markdown 处理类
class MarkdownImageProcessor:
    def __init__(self, output_dir):
        self.output_dir = output_dir
        # 匹配 Markdown 中的图片链接
        self.image_pattern = re.compile(r'!\[.*?\]\((.*?)\)')

    def process_markdown_file(self, md_content, image_urls):
        # 提取 Markdown 文件中的所有图片链接
        image_links = self.image_pattern.findall(md_content)
        if not image_links:
            print("No images found in the markdown file.")
            return md_content

        for image_link in image_links:
            # 标准化路径为文件名（不考虑路径信息）
            image_filename = os.path.basename(image_link)

            # 遍历所有上传的文件，找到与文件名匹配的文件
            found_match = False
            for uploaded_filename in image_urls.keys():
                if image_filename == os.path.basename(uploaded_filename):
                    # 替换为上传后的 MinIO URL
                    md_content = md_content.replace(image_link, image_urls[uploaded_filename])
                    found_match = True
                    break

            if not found_match:
                print(f"Image {image_filename} not found in uploaded files.")

        return md_content


# Flask 路由
@app.route('/')
def upload_form():
    return render_template('upload.html')


@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return redirect(request.url)

    file = request.files['file']
    images = request.files.getlist('images')

    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        file.save(file_path)

        # MinIO 客户端初始化
        minio_client = MinIOClient(
            endpoint="192.168.53.12:9000",
            access_key="gytZQZdmOhe2JZc6yr1k",
            secret_key="TGs7wgbxOuvYCFZ2D5jXuoCOBTlehxJNnODXn0id"
        )
        minio_client.create_bucket("pic")
        minio_client.set_bucket_policy("pic")

        # 上传图片文件
        image_urls = {}
        for image in images:
            if image and allowed_file(image.filename):
                image_filename = secure_filename(image.filename)
                image_path = os.path.join(app.config['UPLOAD_FOLDER'], image_filename)
                image.save(image_path)

                # 上传到 MinIO
                public_url = minio_client.upload_file("pic", image_path, f"kb/{image_filename}")
                if public_url:
                    image_urls[image_filename] = public_url

        # 处理 Markdown 文件
        with open(file_path, 'r', encoding='utf-8') as f:
            md_content = f.read()

        processor = MarkdownImageProcessor(output_dir='uploads')
        updated_content = processor.process_markdown_file(md_content, image_urls)

        updated_file_path = os.path.splitext(file_path)[0] + "_updated.md"
        with open(updated_file_path, 'w', encoding='utf-8') as f:
            f.write(updated_content)

        # 设置响应头，指定文件名和内容类型
        response = make_response(send_file(updated_file_path, as_attachment=True))
        response.headers["Content-Disposition"] = (
            f"attachment; filename*=UTF-8''{urllib.parse.quote(os.path.basename(updated_file_path))}"
        )

        return response

    return redirect(request.url)


if __name__ == "__main__":
    os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)
    app.run(host="0.0.0.0", port=4080)
